package wntransform.validation;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 *
 * @author feki
 */
public class WNTransformValidation {

    /**
     * Validates PL XML
     *
     * @param xmlWhichWillBeValidatedPath
     * @param schemaPath
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public void validatePL(String xmlWhichWillBeValidatedPath, String schemaPath) throws IOException, SAXException, ParserConfigurationException {

        validateXML(xmlWhichWillBeValidatedPath, schemaPath);

    }

    /**
     * Validates CZ XML, the validated XML will be written in 
     * 'wellFormedCZFile.xml' file.
     * 
     * @param xmlWhichWillBeValidatedPath
     * @param schemaPath
     * @throws SAXException
     * @throws IOException
     * @throws ParserConfigurationException
     */
    public void validateCZ(String xmlWhichWillBeValidatedPath, String schemaPath) throws SAXException, IOException, ParserConfigurationException {

        String wellFormedFile = "wellFormedCZFile.xml";
        
        addRootElementToTheXML(xmlWhichWillBeValidatedPath, wellFormedFile);

        validateXML( wellFormedFile, schemaPath);
    }

    /**
     * Writes to the given output file the input file with root element
     *
     * @param inputXMLPath to this file will be root element added
     * @param outputXMLPath to this file will be changed input file written
     * @throws IOException
     */
    private void addRootElementToTheXML(String inputXMLPath, String outputXMLPath) throws IOException {

        BufferedReader in = new BufferedReader(new FileReader(inputXMLPath));
        BufferedWriter out = new BufferedWriter(new FileWriter(outputXMLPath));
        String oneLine;

        try {
            out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");

            out.write("<root>");
            while ((oneLine = in.readLine()) != null) {

                if (oneLine.contains("&")) {
                    oneLine = oneLine.replaceAll("&", "&amp;");
                }
                if (oneLine.contains("\\>")) {
                    oneLine = oneLine.replaceAll("\\>", "&gt;");
                }
                if (oneLine.contains("\\<")) {
                    oneLine = oneLine.replaceAll("\\<", "&lt;");
                }

                out.write(oneLine);
                out.newLine();

            }
            out.write("</root>");
        } catch (IOException ex) {

            System.err.println("An error occured when reading file");
        } finally {

            try {
                in.close();
                out.close();

            } catch (IOException ex) {

                System.err.println("An error occured when reading file");
            }

        }


    }

    /**
     * Help method which validates given document, when it is valid document according to given schema then returns
     * true, false otherwise
     *
     * @param xmlPath, path to the XML file which will be validated
     * @param schemaPath path to the schema by which the XML will be validated
     * @return when it is valid document according to given schema then returns
     * true, false otherwise
     * @throws SAXException
     * @throws IOException
     * @throws ParserConfigurationException
     */
    private void validateXML(String xmlPath, String schemaPath) throws SAXException, IOException, ParserConfigurationException {

        DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document document = parser.parse(new File(xmlPath));

        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

        Source schemaFile = new StreamSource(new File(schemaPath));
        Schema schema = factory.newSchema(schemaFile);

        Validator validator = schema.newValidator();

        validator.validate(new DOMSource(document));

    }
}
